﻿
using AlarmModule;
using AlarmModule.DbContexts;
using AlarmModule.Interface;
using AlarmModule.Interface.Implementation;
using DryIoc;
using LoginModule;
using LoginModule.Models;
using LogModule;
using LogModule.Interface;
using LogModule.Interface.Imp;
using Microsoft.EntityFrameworkCore;
using MonitorModule;
using MonitorModule.DbContexts;
using Prism.Dialogs;
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using ProductMonitor.DbContexts;
using ProductMonitor.ViewModels;
using ProductMonitor.Views;
using StaffModule;
using System;
using System.Threading.Tasks;
using System.Windows;
using WorkshopModule;
using LogLevel = NLog.LogLevel;

namespace ProductMonitor {
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication {


        #region 初始化全局配置OnStartup,第一
        /// <summary>
        /// 作为 WPF 应用程序的生命周期起点，在应用启动时触发:
        /// 通常用于初始化全局配置（如日志、异常处理），但在此代码中仅输出调试信息并调用基类方法。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnStartup(StartupEventArgs e) {

            // 在异常处理前记录启动日志

            RegisterEvents();//全局异常配置
            base.OnStartup(e);// 调用基类确保框架初始化,不调用运行不起来
        }

        #endregion

        #region 注册,第二
        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry) {

            #region 日志

            // 注册日志服务（单例模式）
            containerRegistry.RegisterSingleton<ILogService, LogService>();

            //写个延迟解析版
            //containerRegistry.Register<IAlarmSubscriber>(c => {
            //    var logger = c.Resolve<ILogService>();
            //    var dbContext = c.Resolve<AlarmDbContext>(); // 从容器获取
            //    return new LogAlarmNotifier(logger, dbContext);
            //});
            containerRegistry.RegisterScoped<LogAlarmNotifier>();
            #endregion

            containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();

            containerRegistry.RegisterScoped<ProductMonitorDbContext>(provider => {
                var optionsBuilder = new DbContextOptionsBuilder<ProductMonitorDbContext>();
                optionsBuilder.UseSqlite("Data Source=D:\\Projects\\sqlite\\productMonitor.db;");
                return new ProductMonitorDbContext(optionsBuilder.Options);
            });

        }
        #endregion

        #region 模块登记,第三
        /// <summary>
        /// 
        /// 添加模块
        /// 配置模块登记/目录
        /// </summary>
        /// <param name="moduleCatalog"></param>
        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) {

            moduleCatalog.AddModule<LogProfile>();

            moduleCatalog.AddModule<AlarmProfile>();

            moduleCatalog.AddModule<MonitorProfile>();

            moduleCatalog.AddModule<WorkshopProfile>();

            moduleCatalog.AddModule<LoginProfile>();

            moduleCatalog.AddModule<StaffProfile>();

            base.ConfigureModuleCatalog(moduleCatalog);
        }
        #endregion

        #region 启动页,第四
        /// <summary>
        /// 
        /// 启动页
        /// </summary>
        /// <returns></returns>
        protected override Window CreateShell() {
            //启动页就是Main页面
            return Container.Resolve<MainWindow>();
        }
        #endregion

        #region 应用程序初始化,第五
        /// <summary>
        /// 
        ///​​应用程序启动时的初始化逻辑​​
        /// </summary>
        protected override void OnInitialized() {

            var dialogService = Container.Resolve<IDialogService>();

            dialogService.ShowDialog("LoginUC", callback => {
                if (callback.Result != ButtonResult.OK) {//没登陆
                    Environment.Exit(0);
                    return;
                }
                //登录成功,则进入我们的主窗口,在此之前,还有下面一堆操作
                var mainWindowVM = Application.Current.MainWindow.DataContext as MainWindowViewModel;

                if (mainWindowVM != null) {
                    // 获取登录用户名并设置默认导航
                    if (callback.Parameters.ContainsKey("AccountInfoModel")) {//没找到AccountInfoModel
                        AccountInfoModel info = callback.Parameters.GetValue<AccountInfoModel>("AccountInfoModel");
                        mainWindowVM.SetDefaultNav("MonitorUC", info);//在这里设置登录之后的默认首页
                    }
                }
                // 登录成功: 调用基类初始化方法
                base.OnInitialized();
            });

        }
        #endregion

        #region 全局异常配置
        /// <summary>
        /// 全局异常配置
        /// </summary>
        private void RegisterEvents() {
            //Task线程内未捕获异常处理事件
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;//Task异常 

            //UI线程未捕获异常处理事件（UI主线程）
            DispatcherUnhandledException += App_DispatcherUnhandledException;

            //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }

        //Task线程内未捕获异常处理事件
        private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) {
            try {
                var exception = e.Exception as Exception;
                if (exception != null) {
                    HandleException(exception);
                }
            } catch (Exception ex) {
                HandleException(ex);
            } finally {
                e.SetObserved();
            }
        }

        //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)      
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            try {
                var exception = e.ExceptionObject as Exception;
                if (exception != null) {
                    HandleException(exception);
                }
            } catch (Exception ex) {
                HandleException(ex);
            } finally {
                //ignore
            }
        }

        //UI线程未捕获异常处理事件（UI主线程）
        private static void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {
            try {
                HandleException(e.Exception);
            } catch (Exception ex) {
                HandleException(ex);
            } finally {
                e.Handled = true;
            }
        }

        //日志记录
        private static void HandleException(Exception ex) {
            MessageBox.Show("出错了，请与开发人员联系：" + ex.Message);
            //记录日志

        }
        #endregion

    }
}
